#include "handmade_hero.h"

 INTERNAL void GameOutputSound(game_sound_output_buffer* soundBuffer, int toneHz)
 {
    LOCAL_PERSIST real32 tSine = 0.0f;
    int16 toneVolume = 3000;
    int wavePeriod = soundBuffer->samplesPerSecond / toneHz;

    int16* sampleOut = soundBuffer->samples;
    for (int sampleIndex = 0; sampleIndex < soundBuffer->sampleCount; ++sampleIndex)
    {
        real32 sineValue = sinf(tSine);
        int16 sampleValue = (int16)(sineValue * toneVolume);
        *sampleOut++ = sampleValue; // 左声道
        *sampleOut++ = sampleValue; // 右声道

        tSine += 2.0f * Pi32 * 1.0f / (real32)wavePeriod;
        if (tSine > 2.0f * Pi32)
        {
            tSine -= 2.0f * Pi32;
        }
    }
 }

INTERNAL void RenderWeirdGradient(const game_offscreen_buffer *buffer, int blueOffset, int greenOffset)
{
    /*
                    WIDTH ->
                                                                        Width*BytesPerPixel
    BitmapMemory -> row 0  BB GG RR xx  BB GG RR xx  BB GG RR xx ...
    BM +  Pitch     row 1  BB GG RR xx  BB GG RR xx  BB GG RR xx ...

    */
    uint8 *row = (uint8 *)buffer->memory;
    for (int y = 0; y < buffer->height; ++y)
    {
        uint32 *pixel = (uint32 *)row;
        for (int x = 0; x < buffer->width; ++x)
        {
            /*
                MEMORY ORDER: RR GG BB xx
                LOADED IN:    xx BB GG RR   小端序
                WANTED:       xx RR GG BB   Windows交换R通道和B通道，不管padding
                MEMORY ORDER: BB GG RR xx   Windows交换R和B

                Memory:     BB GG RR xx
                Register:   xx RR GG BB

                pixel (32-bits)
            */
            // 根据位置设置不同的颜色，蓝色通道取x的值，绿色通道取y的值，红色通道取0
            uint8 blue = (uint8)(x + blueOffset);
            uint8 green = (uint8)(y + greenOffset);

            *pixel++ = ((green << 8) | blue); // 各通道组合为当前像素的RBG值
        }
        row += buffer->pitch;
    }
}

INTERNAL void GameUpdateAndRender(game_memory* memory, game_input *input, const game_offscreen_buffer* buffer)
{
    Assert((&input->controllers[0].terminator - &input->controllers[0].buttons[0]) == (ArrayCount(input->controllers[0].buttons)));
    Assert(sizeof(game_state) <= memory->permanentStorageSize);
    
    game_state* gameState = (game_state*)memory->permanentStorage;
    if (!memory->isInitialized)
    {
        char* filename = __FILE__;

        debug_read_file_result file = DEBUGPlatformReadEntireFile(filename);
        if (file.contents)
        {
            DEBUGPlatformWriteEntireFile("test.out", file.contentSize, file.contents);
            DEBUGPlatformFreeFileMemory(file.contents);
        }
        gameState->toneHz = 512;

        memory->isInitialized = true;
    }

    for (int controllerIndex = 0; controllerIndex < ArrayCount(input->controllers); ++controllerIndex)
    {
        game_controller_input* controller = GetController(input, controllerIndex);
        if (controller->isAnalog)
        {
            // NOTE: Use analog movement tuning
            gameState->blueOffset += (int)(4.0f * (controller->stickAverageX));
            gameState->toneHz = 512 + (int)(128.0f * (controller->stickAverageY));
        }
        else
        {
            // NOTE: Use digital movement tuning
            if (controller->moveLeft.endedDown)
            {
                gameState->blueOffset -= 1;
            }

            if (controller->moveRight.endedDown)
            {
                gameState->blueOffset += 1;
            }
        }

        if (controller->actionDown.endedDown)
        {
            gameState->greenOffset += 1;
        }
    }

    RenderWeirdGradient(buffer, gameState->blueOffset, gameState->greenOffset);
}

INTERNAL void GameGetSoundSamples(game_memory* memory, game_sound_output_buffer* soundBuffer)
{
    game_state* gameState = (game_state*)memory->permanentStorage;
    GameOutputSound(soundBuffer, gameState->toneHz);
}